/* Copyright (c) 2011, Damjan Jovanovic <damjan dot jov aaa aaatt t tt gmail>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the author nor the
 *       names of the contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package com.googlecode.raisinrefinery;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Map;

public class ProcessUtils {
    private static class OutputCollector {
        private InputStream is;
        private LinkedList<String> output = new LinkedList<String>();
        private Thread t;

        public OutputCollector(InputStream is) {
            this.is = is;
        }

        public void start() {
            t = new Thread(new Runnable() {
                public void run() {
                    thread();
                }
            });
            t.start();
        }

        private void thread() {
            BufferedReader r = null;
            try {
                r = new BufferedReader(new InputStreamReader(is, "UTF-8"));
                String line;
                while ((line = r.readLine()) != null) {
                    output.addLast(line);
                }
            } catch (IOException ioEx) {
            } finally {
                Main.safelyClose(r);
            }
        }

        public LinkedList<String> getOutput() {
            t.interrupt();
            try {
                t.join();
            } catch (InterruptedException interrupted) {
            }
            return output;
        }
    }

    public static LinkedList<String> runAndCollectOutputFor(File workingDir,
            Map<String,String> envVars, String... command) throws IOException {
        ProcessBuilder pb = new ProcessBuilder(command);
        pb.directory(workingDir);
        pb.redirectErrorStream(true);
        if (envVars != null) {
            Map<String,String> env = pb.environment();
            env.putAll(envVars);
        }
        
        Process process = null;
        try {
            process = pb.start();
            OutputCollector outputCollector = new OutputCollector(process.getInputStream());
            outputCollector.start();
            int exitCode = process.waitFor();
            LinkedList<String> output = outputCollector.getOutput();
            if (exitCode != 0) {

                File logFile = File.createTempFile("winebarrelbuilder", ".txt");
                writeOutput(output, logFile);
                throw new IOException("Exit code " + exitCode + " for " +
                        Arrays.toString(command) + ", output written to " +
                        logFile);
            }
            return output;
        } catch (InterruptedException interrupted) {
            throw new IOException(interrupted);
        } finally {
            if (process != null) {
                Main.safelyClose(process.getErrorStream());
                Main.safelyClose(process.getInputStream());
                Main.safelyClose(process.getOutputStream());
            }
        }
    }

    public static void writeOutput(LinkedList<String> output, File file) throws IOException {
        BufferedWriter writer = null;
        try {
            writer = new BufferedWriter(new FileWriter(file));
            for (String line : output) {
                writer.write(line);
                writer.newLine();
            }
        } finally {
            Main.safelyClose(writer);
        }
    }
}
